﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ComLib.ComType;
using System.IO;
using System.Diagnostics;
using LogLib;
using System.IO.MemoryMappedFiles;
using System.Threading;
using ComLib;
using ComLib.ComFun;

namespace CoreBroker
{
    public partial class CapturerBroker : UserControl
    {
        private const string CapturerAppFileName = "NewCapturerDemo.exe";
        private const string CapturerAppName = "NewCapturerDemo";
        /// <summary>
        /// 当照片捕获成功时，激发程序中处理该照片的事件
        /// </summary>
        public EventHandler PhotoCaptured;

        /// <summary>
        /// 当照片被捕获
        /// </summary>
        protected void OnPhotoCaptured()
        {
            if (PhotoCaptured != null)
            {
                PhotoCaptured(null, null);
            }
        }

        /// <summary>
        /// 当播放器中断时
        /// </summary>
        public PlayingAbortEventHandler PlayingAbort;
        protected void OnPlayerAborted(object sender, PlayingAbortEventArgs e)
        {
            if (this.InvokeRequired)
            {
                PlayingAbortEventHandler outdelegate
                    = new PlayingAbortEventHandler(OnPlayerAborted);
                this.BeginInvoke(outdelegate, new object[] { sender, e });
                return;
            }
            Log.WriteAsync(string.Format("检测到镜头发生了错误, 原因:{0}", e.Error));
            if (PlayingAbort != null)
            {
                PlayingAbort(sender, e);
            }
        }

        public void RemoveAllEvents()
        {
            PlayingAbort = null;
            PhotoCaptured = null;
        }

        public CapturerBroker()
        {
            InitializeComponent();
        }

        #region Handling in NewCapturerDemo.exe

        /// <summary>
        /// 镜头画面视频流采集和播放进程
        /// </summary>
        private Process Capturer = null;

        private WindowEmbedder Embedder = new WindowEmbedder();

        /// <summary>
        /// 照片采集进程的窗口句柄
        /// </summary>
        private IntPtr CapturerWindowHandle = IntPtr.Zero;

        /// <summary>
        /// 关闭已经存在的进程
        /// </summary>
        /// <param name="processName"></param>
        protected static void KillProcess(string processName)
        {
            Process[] processes = Process.GetProcesses();
            foreach (Process p in processes)
            {
                try
                {
                    if (p.ProcessName.Contains(processName))
                    {
                        Log.WriteAsync("Capturer process 已经存在，中止该进程");
                        p.Kill();
                        p.WaitForExit();
                        p.Close();
                        Log.WriteAsync("进程" + p.ProcessName + "已关闭");
                    }
                }
                catch
                {

                }
            }
        }

        /// <summary>
        /// 判断指定名称的进程是否已经存在
        /// </summary>
        /// <param name="processName"></param>
        protected bool ExistProcess(string processName)
        {
            if (Capturer != null)
            {
                if (!Capturer.HasExited)
                {
                    return true;
                }
            }
            Process[] processes = Process.GetProcesses();          
            foreach (Process p in processes)
            {
                try
                {
                    if (p.ProcessName.Contains(processName))
                    {
                        Capturer = p;
                        return true;
                    }
                }
                catch
                {
                    continue;
                }
            }
            return false;
        }

        /// <summary>
        /// 判断指定进程是否存在，不存在重启进程，然后开始工作
        /// </summary>
        public void RestartWork()
        {
            if (ExistProcess(CapturerAppName))
            {
                Log.WriteAsync("照相程序待机正常，开始工作了");
                StartWork();
            }
            else
            {
                Log.WriteAsync("照相程序意外关闭了，重启拍照程序开始工作");
                StartCapturerProcess();
                // 延时执行嵌入过程
                AsyncTask.Delay(1, StartWork);
            }      
        }

        public void StartWork()
        {
            if (this.InvokeRequired)
            {
                Action handler = new Action(StartWork);
                this.Invoke(handler, new object[] { });
                return;
            }
            if (FixWindowLocation())
            {
                StartCapturer();
            }
            else
            {
                MessageBox.Show("嵌入照相程序失败!");
            }
        }

        private void StartCapturerProcess()
        {
            IntPtr MainWindowHandle = Win32API.GetCurrentWindowHandle();
            string fileName = string.Format(@"{0}\Capturer\{1}", Application.StartupPath, CapturerAppFileName);
            if (File.Exists(fileName))
            {
                KillProcess(CapturerAppName);
                ProcessStartInfo Info = new ProcessStartInfo();
                Info.FileName = fileName;
                Info.CreateNoWindow = false;
                Info.WindowStyle = ProcessWindowStyle.Minimized;
                Info.Arguments = MainWindowHandle.ToString() + " " + this.Handle.ToInt32().ToString();
                Capturer = Process.Start(Info);
            }
            else
            {
                MessageBox.Show("文件不存在" + fileName);
            }
        }

        /// <summary>
        /// 定位照片采集进程窗口
        /// </summary>
        private bool FixWindowLocation()
        {           
            Embedder.EmbedProcess(Capturer, this);
            CapturerWindowHandle = Embedder.MainWindowHandle;
            if (CapturerWindowHandle != IntPtr.Zero)
            {
                Log.WriteAsync("窗口查找成功.");
                return true;
            }
            else
            {
                Log.WriteAsync("窗口查找失败.");
                return false;
            }
        }
        #endregion

        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            switch (m.Msg)
            {
                case WindowsMessage.WM_COPYDATA:
                    OnCustomMsgReceived(m);
                    break;
                default:
                    break;
            }
            base.WndProc(ref m);
        }


        /// <summary>
        /// 处理来自其他进程发来的消息
        /// </summary>
        /// <param name="m"></param>
        private void OnCustomMsgReceived(System.Windows.Forms.Message m)
        {
            COPYDATASTRUCT mystr = new COPYDATASTRUCT();
            Type mytype = mystr.GetType();
            mystr = (COPYDATASTRUCT)m.GetLParam(mytype);
            string message = mystr.lpData;
            int id = (int)m.WParam;
            switch (id)
            {
                case CustomWindowsMessage.MSG_CAP_PHOTO_OK:
                    OnPhotoCaptured();
                    Log.WriteAsync("收到拍照成功消息:" + message);
                    break;
                case CustomWindowsMessage.MSG_CAP_ERROR:
                    {
                        Log.WriteAsync("收到镜头意外中断播放的消息:" + message);
                        OnPlayerAborted(this, new PlayingAbortEventArgs(message));
                    }                    
                    break;
                case CustomWindowsMessage.MSG_CAP_START_OK:
                    Log.WriteAsync("收到镜头启动成功的消息.");
                    break;
                case CustomWindowsMessage.MSG_CAP_START_FAIL:
                    Log.WriteAsync("收到镜头启动失败的消息.");
                    break;
                case CustomWindowsMessage.MSG_CAP_STOP_OK:
                    Log.WriteAsync("收到镜头停止成功的消息.");
                    break;
                case CustomWindowsMessage.MSG_CAP_STOP_FAIL:
                    Log.WriteAsync("收到镜头停止失败的消息.");
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// 通知被监测应用程序执行指定的命令
        /// </summary>
        /// <param name="command">消息内容</param>
        private void SendCommand(int command)
        {
            if(this.InvokeRequired)
            {
                Action<int> outdelegate = new Action<int>(SendCommand);
                this.BeginInvoke(outdelegate, new object[] { command });
                return;
            }
            int uMsg = WindowsMessage.WM_COPYDATA;
            int wParam = command;
            string strMsgText = "Command";
            int nLen = Encoding.Unicode.GetBytes(strMsgText).Length;
            COPYDATASTRUCT dataStr = new COPYDATASTRUCT();
            dataStr.dwData = this.Handle;
            dataStr.cbData = nLen;
            dataStr.lpData = strMsgText;
            WindowsAPI.SendMessage(CapturerWindowHandle, uMsg, wParam, ref dataStr);

        }

        /// <summary>
        /// 通知被监测应用程序执行关闭窗口的命令
        /// </summary>
        private void SendCloseCommand()
        {
            WindowsAPI.SendMessage(CapturerWindowHandle, WindowsMessage.WM_CLOSE, 0, 0);
        }


        public void OnShottingCompleted()
        {

        }

        /// <summary>
        /// 打开镜头设置参数对话框
        /// </summary>
        public void OpenCameraSettings()
        {
            SendCommand(CustomWindowsMessage.MSG_CAP_SETTING);
        }

        /// <summary>
        /// 重新启动播放器
        /// </summary>
        public void RestartCapturer()
        {
            SendCommand(CustomWindowsMessage.MSG_CAP_RESTART);
        }

        public void StartCapturer()
        {
            SendCommand(CustomWindowsMessage.MSG_CAP_START);
        }

        /// <summary>
        /// 设置相机的默认参数
        /// </summary>
        public void SetDefalutProperties()
        {
            SendCommand(CustomWindowsMessage.MSG_CAP_SETTING_DEFAULT);
        }

        /// <summary>
        /// 增加快门时间（调高亮度）
        /// </summary>
        public void AddShutterTime()
        {
            SendCommand(CustomWindowsMessage.MSG_CAP_SETTING_ADD_SHUTTER_TIME);
        }

        /// <summary>
        /// 减少快门时间（降低亮度）
        /// </summary>
        public void DecShutterTime()
        {
            SendCommand(CustomWindowsMessage.MSG_CAP_SETTING_DEC_SHUTTER_TIME);
        }

        public void StopCapturer()
        {
            SendCommand(CustomWindowsMessage.MSG_CAP_STOP);
        }

        public void TakePhoto()
        {
            SendCommand(CustomWindowsMessage.MSG_CAP_DO);
        }

        public void TakeFormalPhoto()
        {
            SendCommand(CustomWindowsMessage.MSG_CAP_DOFORMAL);
        }

        public void CloseCapturer()
        {
            SendCloseCommand();
        }

        public void RegisterPlayingAborted(PlayingAbortEventHandler handler)
        {
            PlayingAbort = handler;
        }

        public void RemovePlayingAborted(PlayingAbortEventHandler handler)
        {
            PlayingAbort = null;
        }    
    }
}
